1
|
|
|
/*jslint devel: true, bitwise: true, regexp: true, browser: true, confusion: true, unparam: true, eqeq: true, white: true, nomen: true, plusplus: true, maxerr: 50, indent: 4 */ |
2
|
|
|
/*globals jQuery */ |
3
|
|
|
|
4
|
|
|
/*! |
5
|
|
|
* Tristate v1.2.1 |
6
|
|
|
* |
7
|
|
|
* Copyright (c) 2013-2017 Martijn W. van der Lee |
8
|
|
|
* Licensed under the MIT. |
9
|
|
|
*/ |
10
|
|
|
/* Based on work by: |
11
|
|
|
* Chris Coyier (http://css-tricks.com/indeterminate-checkboxes/) |
12
|
|
|
* |
13
|
|
|
* Tristate checkbox with support features |
14
|
|
|
* pseudo selectors |
15
|
|
|
* val() overwrite |
16
|
|
|
*/ |
17
|
|
|
|
18
|
|
|
;(function($, undefined) { |
19
|
|
|
'use strict'; |
20
|
|
|
|
21
|
|
|
var pluginName = 'tristate', |
22
|
|
|
defaults = { |
23
|
|
|
'change': undefined, |
24
|
|
|
'checked': undefined, |
25
|
|
|
'indeterminate': undefined, |
26
|
|
|
'init': undefined, |
27
|
|
|
'reverse': false, |
28
|
|
|
'state': undefined, |
29
|
|
|
'unchecked': undefined, |
30
|
|
|
'value': undefined // one-way only! |
31
|
|
|
}, |
32
|
|
|
valFunction = $.fn.val; |
33
|
|
|
|
34
|
|
|
function Plugin(element, options) { |
35
|
|
|
if($(element).is(':checkbox')) { |
36
|
|
|
this.element = $(element); |
37
|
|
|
this.settings = $.extend( {}, defaults, options ); |
38
|
|
|
this._create(); |
39
|
|
|
} |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
$.extend(Plugin.prototype, { |
43
|
|
|
_create: function() { |
44
|
|
|
var that = this, |
45
|
|
|
state; |
46
|
|
|
|
47
|
|
|
// Fix for #1 |
48
|
|
|
if (window.navigator.userAgent.indexOf('Trident') >= 0) { |
49
|
|
|
this.element.click(function(e) { |
50
|
|
|
that._change.call(that, e); |
51
|
|
|
that.element.closest('form').change(); |
52
|
|
|
}); |
53
|
|
|
} else { |
54
|
|
|
this.element.change(function(e) { |
55
|
|
|
that._change.call(that, e); |
56
|
|
|
}); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
this.settings.checked = this.element.attr('checkedvalue') || this.settings.checked; |
60
|
|
|
this.settings.unchecked = this.element.attr('uncheckedvalue') || this.settings.unchecked; |
61
|
|
|
this.settings.indeterminate = this.element.attr('indeterminatevalue') || this.settings.indeterminate; |
62
|
|
|
|
63
|
|
|
// Initially, set state based on option state or attributes |
64
|
|
|
if (typeof this.settings.state === 'undefined') { |
65
|
|
|
this.settings.state = typeof this.element.attr('indeterminate') !== 'undefined'? null : this.element.is(':checked'); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
// If value specified, overwrite with value |
69
|
|
|
if (typeof this.settings.value !== 'undefined') { |
70
|
|
|
state = this._parseValue(this.settings.value); |
71
|
|
|
if (typeof state !== 'undefined') { |
72
|
|
|
this.settings.state = state; |
73
|
|
|
} |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
this._refresh(this.settings.init); |
77
|
|
|
|
78
|
|
|
return this; |
79
|
|
|
}, |
80
|
|
|
|
81
|
|
|
_change: function(e) { |
82
|
|
|
if (e.isTrigger || !e.hasOwnProperty('which')) { |
83
|
|
|
e.preventDefault(); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
switch (this.settings.state) { |
87
|
|
|
case true: this.settings.state = (this.settings.reverse ? false : null); break; |
88
|
|
|
case false: this.settings.state = (this.settings.reverse ? null : true); break; |
89
|
|
|
default: this.settings.state = (this.settings.reverse ? true : false); break; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
this._refresh(this.settings.change); |
93
|
|
|
}, |
94
|
|
|
|
95
|
|
|
_refresh: function(callback) { |
96
|
|
|
var value = this.value(); |
97
|
|
|
|
98
|
|
|
this.element.data("vanderlee." + pluginName, value); |
99
|
|
|
|
100
|
|
|
this.element[this.settings.state === null ? 'attr' : 'removeAttr']('indeterminate', 'indeterminate'); |
101
|
|
|
this.element.prop('indeterminate', this.settings.state === null); |
102
|
|
|
this.element.get(0).indeterminate = this.settings.state === null; |
103
|
|
|
|
104
|
|
|
this.element[this.settings.state === true ? 'attr' : 'removeAttr']('checked', true); |
105
|
|
|
this.element.prop('checked', this.settings.state === true); |
106
|
|
|
|
107
|
|
|
if ($.isFunction(callback)) { |
108
|
|
|
callback.call(this.element, this.settings.state, this.value()); |
109
|
|
|
} |
110
|
|
|
}, |
111
|
|
|
|
112
|
|
|
state: function(value) { |
113
|
|
|
if (typeof value === 'undefined') { |
114
|
|
|
return this.settings.state; |
115
|
|
|
} else if (value === true || value === false || value === null) { |
116
|
|
|
this.settings.state = value; |
117
|
|
|
|
118
|
|
|
this._refresh(this.settings.change); |
119
|
|
|
} |
120
|
|
|
return this; |
121
|
|
|
}, |
122
|
|
|
|
123
|
|
|
_parseValue: function(value) { |
124
|
|
|
if (value === this.settings.checked) { |
125
|
|
|
return true; |
126
|
|
|
} else if (value === this.settings.unchecked) { |
127
|
|
|
return false; |
128
|
|
|
} else if (value === this.settings.indeterminate) { |
|
|
|
|
129
|
|
|
return null; |
130
|
|
|
} |
131
|
|
|
}, |
132
|
|
|
|
133
|
|
|
value: function(value) { |
134
|
|
|
if (typeof value === 'undefined') { |
135
|
|
|
var value; |
136
|
|
|
switch (this.settings.state) { |
137
|
|
|
case true: |
138
|
|
|
value = this.settings.checked; |
139
|
|
|
break; |
140
|
|
|
|
141
|
|
|
case false: |
142
|
|
|
value = this.settings.unchecked; |
143
|
|
|
break; |
144
|
|
|
|
145
|
|
|
case null: |
146
|
|
|
value = this.settings.indeterminate; |
147
|
|
|
break; |
148
|
|
|
} |
149
|
|
|
return typeof value === 'undefined'? this.element.attr('value') : value; |
150
|
|
|
} else { |
|
|
|
|
151
|
|
|
var state = this._parseValue(value); |
152
|
|
|
if (typeof state !== 'undefined') { |
|
|
|
|
153
|
|
|
this.settings.state = state; |
154
|
|
|
this._refresh(this.settings.change); |
|
|
|
|
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
}); |
159
|
|
|
|
160
|
|
|
$.fn[pluginName] = function (options, value) { |
161
|
|
|
var result = this; |
162
|
|
|
|
163
|
|
|
this.each(function() { |
164
|
|
|
if (!$.data(this, "plugin.vanderlee." + pluginName)) { |
165
|
|
|
$.data(this, "plugin.vanderlee." + pluginName, new Plugin(this, options)); |
|
|
|
|
166
|
|
|
} else if (typeof options === 'string') { |
|
|
|
|
167
|
|
|
if (typeof value === 'undefined') { |
168
|
|
|
result = $(this).data("plugin.vanderlee." + pluginName)[options](); |
169
|
|
|
return false; |
170
|
|
|
} else { |
|
|
|
|
171
|
|
|
$(this).data("plugin.vanderlee." + pluginName)[options](value); |
|
|
|
|
172
|
|
|
} |
173
|
|
|
} |
174
|
|
|
}); |
175
|
|
|
|
176
|
|
|
return result; |
177
|
|
|
}; |
178
|
|
|
|
179
|
|
|
// Overwrite fn.val |
180
|
|
|
$.fn.val = function(value) { |
181
|
|
|
var data = this.data("vanderlee." + pluginName); |
182
|
|
|
if (typeof data === 'undefined') { |
183
|
|
|
if (typeof value === 'undefined') { |
184
|
|
|
return valFunction.call(this); |
185
|
|
|
} else { |
|
|
|
|
186
|
|
|
return valFunction.call(this, value); |
187
|
|
|
} |
188
|
|
|
} else { |
|
|
|
|
189
|
|
|
if (typeof value === 'undefined') { |
190
|
|
|
return data; |
191
|
|
|
} else { |
|
|
|
|
192
|
|
|
this.data("vanderlee." + pluginName, value); |
193
|
|
|
return this; |
194
|
|
|
} |
195
|
|
|
} |
196
|
|
|
}; |
197
|
|
|
|
198
|
|
|
// :indeterminate pseudo selector |
199
|
|
|
$.expr.filters.indeterminate = function(element) { |
200
|
|
|
var $element = $(element); |
201
|
|
|
return typeof $element.data("vanderlee." + pluginName) !== 'undefined' && $element.prop('indeterminate'); |
202
|
|
|
}; |
203
|
|
|
|
204
|
|
|
// :determinate pseudo selector |
205
|
|
|
$.expr.filters.determinate = function(element) { |
206
|
|
|
return !($.expr.filters.indeterminate(element)); |
207
|
|
|
}; |
208
|
|
|
|
209
|
|
|
// :tristate selector |
210
|
|
|
$.expr.filters.tristate = function(element) { |
211
|
|
|
return typeof $(element).data("vanderlee." + pluginName) !== 'undefined'; |
212
|
|
|
}; |
213
|
|
|
})(jQuery); |
214
|
|
|
|
This check looks for functions where a
return
statement is found in some execution paths, but not in all.Consider this little piece of code
The function
isBig
will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly returnundefined
.This behaviour may not be what you had intended. In any case, you can add a
return undefined
to the other execution path to make the return value explicit.